#! /usr/bin/env python
# ______________________________________________________________________
"""Grammarian

The Basil Grammarian application top level script.

Jonathan Riehl

$Id$
"""
# ______________________________________________________________________
# Module imports

import sys
import getopt
import string
from basil.apps.grammarian_util import commands, misc
from basil.models.grammar import BasilGrammarModel, GrammarUtils

# ______________________________________________________________________
# Module data

__DEBUG__ = misc.__DEBUG__

VERSION = misc.VERSION

COMMANDS = commands.COMMANDS

COMMAND_HELP = commands.COMMAND_HELP

# ______________________________________________________________________
# Module utility functions

def printUsage ():
    """printUsage()
    Print the usage of the Grammarian script.
    """
    usageStr = '''Usage:
    %% Grammarian [Options] [command [Commandoptions]]

Options:
    -d: Enable debugging output.
    -f <format>: Specify input format (bnf, pgen, bison, etc...)
    -g: Use Tkinter-based GUI.  (The GUI will abort any other command given
        from the command line.)
    -G: Use GTK-based GUI.  (As above, this will abort any other commands.)
    -h: Display (this) usage help or give help for specific command (if a
        command is given.)
    -i <filename>: Specify input file name (default is to read from stdin.)
    -o <filename>: Specify output file name (default is to write to stdout.)

Commands: %s
Default command is "output".
'''
    print >>sys.stderr, usageStr % (string.join(COMMANDS.keys(), ", "))

# ______________________________________________________________________

def getChildElementByElemName (modelElement, name, startIndex = 0):
    """getChildElementByElemName()
    Return the first child instance with the given element name.
    """
    return (child for child in modelElement
            if child.elementName == name).next()

# ______________________________________________________________________

def getChildElementsByElemName (modelElement, name, startIndex = 0):
    """getChildElementsByElemName()
    Similar to a filter() operation on the passed model element, returning
    a list of child elements with the given element name.
    """
    return [child for child in modelElement if child.elementName == name]

# ______________________________________________________________________
# Main routine
# ______________________________________________________________________

def main (*args):
    print >>sys.stderr, "Grammarian, Version %s" % VERSION
    # ____________________________________________________________
    global __DEBUG__
    command = None
    commandArgs = []
    commandFunction = None
    graphical = None
    help = False
    inFile = None
    inFormat = None
    outFile = None
    retVal = 0
    # ____________________________________________________________
    opts, args = getopt.getopt(args, "df:gGhi:o:")
    for (optFlag, optArg) in opts:
        if optFlag == "-d":
            __DEBUG__ = True
        elif optFlag == "-f":
            inFormat = string.lower(optArg)
        elif optFlag == "-g":
            graphical = "TK"
        elif optFlag == "-G":
            graphical = "GTK"
        elif optFlag == "-h":
            help = True
        elif optFlag == "-i":
            inFile = optArg
        elif optFlag == "-o":
            outFile = optArg
    if len(args) > 0:
        command = args[0]
        commandArgs = args[1:]
    if (command != None) and (not COMMANDS.has_key(command)):
        print >>sys.stderr, "Unsupported command!"
        help = True
        retVal = -1
    # ____________________________________________________________
    if __DEBUG__:
        sys.stderr.write("""
        Command:          %s
        Command args:     %s
        Command function: %s
        Graphical:        %s
        Help:             %s
        Input file:       %s
        Input format:     %s
        Output file:      %s\n\n""" %
                         (command,
                          commandArgs,
                          commandFunction,
                          graphical,
                          help,
                          inFile,
                          inFormat,
                          outFile))
    # ____________________________________________________________
    # Either open the GUI or ensure there is a command being invoked.
    if graphical:
        gui_module_name = ("basil.apps.grammarian_util.%sGrammarianApp" %
                           graphical)
        if __DEBUG__:
            print >>sys.stderr, "gui_module_name =", gui_module_name
        gui_module = __import__(gui_module_name, fromlist = ["main"])
        gui_module.main()
    else:
        if (not help) and (command == None):
            print >>sys.stderr, ("Warning: No command given, using default of "
                                 "'output'.")
            command = 'output'
        # Either display help or run the command line function.
        if not help:
            commandFunction = COMMANDS[command]
            model = GrammarUtils.getModel(inFile, inFormat,
                                          misc.grammarModelFactory)
            retVal = commandFunction(inFile, model, outFile, commandArgs)
        else:
            if command == None:
                printUsage()
            else:
                print "Command usage:"
                print COMMAND_HELP[command]
    sys.exit(retVal)

# ______________________________________________________________________

if __name__ == "__main__":
    main(*sys.argv[1:])

# ______________________________________________________________________
# End of Grammarian
